package com.fengyun.scala

import scala.collection.mutable
import scala.collection.parallel.mutable.ParArray

/**
 * @author Hanpeng
 * @date 2021/1/22 17:05
 * @description:  Arrays 是可变的,索引的值的集合。对标java中的固定长度数组。
 *                有两个隐式转换(implicit conversions),scala.Predef经常被用于数组,
 *                scala.collection.mutable.ArrayOps 以及 scala.collection.mutable.WrappedArray
 *                这两个API提供了Scala collection API的标准操作。ArrayOps 是临时的,返回一个新的对象Array。
 *                而WrappedArray返回原来的
 *                ===========================
 *                转换操作ArrayOps 比 WrappedArray的优先级高,
 *
 *                val arr = Array(1, 2, 3)
 *                val arrReversed = arr.reverse
 *                val seqReversed : Seq[Int] = arr.reverse
 *                arrReversed是Array[Int]类型,ArrayOps 来执行reverse操作。
 *                将会计算 首先转换为WrappedArray 然后再执行reverse 操作 这就是临时和永久的区别
 *                这就是临时和永久的区别。
 *                ===========================
 *
 */
object TestArray {
  def main(args: Array[String]): Unit = {
    //创建并完成初始化
    val ints: Array[Int] = Array(1, 2, 3, 4)
    //syntactic sugar 调用 apply(Int)
    val first: Int = ints(0);
    println(first);
    //syntactic sugar 调用update(Int, T)
    ints(3) = 100;
    //ints(10)=100; 固定数组 如果超过 报异常
    val ints1: Array[Int] = ints.map((num) => {
      num * 2
    })
    val ints2: Array[Int] = ints.map(_ * 2)
    println(ints) //还是原来的值
    println(ints1) //新的值
    println(ints.eq(ints1))
    // 优先级高代码
    val arr: Array[Int] = Array(1, 2, 3)
    val arrReversed: Array[Int] = arr.reverse //ArrayOps  reverse  Returns new sequence with elements in reversed order
    println(arr.eq(arrReversed))
    println(arr)
    val seqReversed: Seq[Int] = arr.reverse //WrappedArray reverse  Returns new sequence with elements in reversed order.

    println(arr.eq(seqReversed))
    println(arr)
    //创建一个有10个元素的数组
    val array: Array[String] = new Array[String](10);
    //
    val jiajia1: Array[Int] = Array(1, 2);
    val jiajia2: Array[Int] = Array(3, 4);
    val jiajiahe12: Array[Int] = jiajia1 ++ jiajia2
    println(jiajiahe12)
    //和++表达的含义一样 只是返回值类型由 :右边操纵数的类型决定
    val jiajia3: Array[Int] = Array(1, 2);
    val jiajia4: Array[Int] = Array(2, 4);
    val jiajia34he: Any = jiajia3 ++: jiajia4;
    println(jiajia34he)
    //
    val jiajia5: Array[Int] = Array(1, 2);
    val jiajia6: Array[String] = Array("2", "4")
    val jiajia56he: Array[Any] = jiajia5 ++: jiajia6;
    println(jiajia56he.getClass.getName)
    //+:  最后变成9 1 2  在数组头加一个元素
    var jiajia7: Array[Int] = Array(1, 2);
    val jiajia7he = 9 +: jiajia7;
    println(jiajia7he.getClass.getName)
    // /:  从左往右 等同:\
    //  :\  从右往左   5+4+3+2+1
    var jiajia8: Array[Int] = Array(1, 2, 3, 4);
    val i: Int = (jiajia8 :\ 5) ((x, y) => {
      x + y
    })
    println(i)
    // :+  元素加在末尾
    var jiajia9: Array[Int] = Array(1, 2);
    val jiajia9he = jiajia7 :+ 9;
    println(jiajia9he)
    //  dsdsd12
    var jiajia10: Array[Int] = Array(1, 2);
    val jiajia10str: StringBuilder = jiajia10.addString(new StringBuilder("dsdsd"))
    println(jiajia10str)
    //aggregate  返回值不知道是什么意思
    var jiajia11: Array[Int] = Array(1, 2);
    val i1: Int = jiajia11.aggregate(2)(
      (x, y) => {
        x * y
      },
      (m, n) => {
        m + n
      })
    println(i1)
    //def apply(i: Int)  返回对应索引的值
    println(jiajia11.apply(0))
    //def canEqual(that: Any)  判断两个对象是否可以比较
    var jiajia12: Array[Int] = Array(1, 2);
    var jiajia13: Array[Int] = Array(3, 4);
    println(jiajia12.canEqual(jiajia13))
    //charAt(index: Int): Char  只能用于char 数组
    val chars: Array[Char] = Array('a', 'b', 'c')
    println("c:" + chars.charAt(0))
    // clone 两个对象不一样
    val clone1: Array[Int] = jiajia12.clone()
    // def collect[B](pf: PartialFunction[A, B]): Array[B]  偏函数的概念
    var collectArr: Array[Int] = Array(1, 2);
    val fun: PartialFunction[Int, Int] = {
      case x: Int => x * 100
    }
    //这样每个值都乘以了100
    val ints3: Array[Int] = collectArr.collect(fun)
    //def collectFirst[B](pf: PartialFunction[T, B]): Option[B]
    //def combinations(n:Int)  实际上是对各个元素进行排列组合
    val combinations: Array[Int] = Array(11, 22, 33);
    val iteratorCombinations: Iterator[Array[Int]] = combinations.combinations(2)
    iteratorCombinations.foreach((nn) => {
      println(nn.mkString(","))
    })
    //def contains[A1 >: A](elem: A1): Boolean
    //def containsSlice[B](that: GenSeq[B]): Boolean 是否包含一个切片
    //def copyToArray
    //def corresponds 判断两个序列长度以及对应位置元素是否符合某个条件
    //def count 判断满足条件的元素的值
    //def deep  Array==>IndexedSeq
    val a = Array(1, 2, 4, 3) //a: Array[Int] = Array(1, 2, 4, 3)
    val b: IndexedSeq[Any] = a.deep
    println(a) //[I@2ac5ba7a
    println(b) //Array(1, 2, 4, 3)
    //def diff(that: collection.Seq[T]): Array[T]
    val adiff = Array(1, 2, 3, 4)
    val bdiff = Array(4, 5, 6, 7)
    val cdiff = adiff.diff(bdiff)
    println(cdiff.mkString) //1,2,3
    //def distinct: Array[T] 去除重复元素
    //drop(n: Int) 去除前两个 索引0和1
    //dropRight(n: Int)  尾部
    //dropWhile(p: (T) ⇒ Boolean) 去除符合条件的元素
    //endsWith[B](that: GenSeq[B]): Boolean  是否以一个给定的序列结尾
    //exists 是否包含某个元素
    //def filter(p: (T) ⇒ Boolean): Array[T] 满足filter的返回
    //filterNot  不满足的返回
    //def find(p: (T) ⇒ Boolean): Option[T] 查找第一天满足条件的
    //def flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): Array[B]
    val aFlatMap = Array(1, 2, 3, 4)
    val bFlatMap = a.flatMap(x => {
      1 to x
    }) //先对每个元素执行操作 返回一个数组 然后再将数组合并
    println(bFlatMap.mkString(",")) //结果：1,1,2,1,2,3,1,2,3,4
    //def flatten[U](implicit asTrav: (T) ⇒ collection.Traversable[U], m: ClassTag[U]): Array[U]
    // 将二维数组的所有元素联合在一起，形成一个一维数组返回（要求数组中元素的维度保持一致，否则报错）
    val dArrFlatten = Array(Array(1, 2, 3), Array(4, 5, 6))
    val cFlatten = dArrFlatten.flatten
    println(cFlatten.mkString(",")) //1,2,3,4,5,6
    //def fold[A1 >: A](z: A1)(op: (A1, A1) ⇒ A1): A1  对序列中的每个元素进行二元运算
    val aFold = Array(1, 2, 3, 4)
    //区分aggregate：fold同aggregate有类似的语义，但执行过程有所不同（aggregate需要两个处理方法）
    val i2: Int = aFold.fold(10)((m, n) => { //把初始值顺序10和每个元素相加，把得到的结果与下一个元素进行运算
      m + n
    })
    //def foldLeft[B](z: B)(op: (B, T) ⇒ B): B
    //def foldRight[B](z: B)(op: (B, T) ⇒ B): B
    //def forall(p: (T) ⇒ Boolean): Boolean  测试数组中的元素是否都满足条件 空数组返回true
    //def foreach(f: (A) ⇒ Unit): Unit   给定一个函数 应用于所有的元素
    //def groupBy[K](f: (T) ⇒ K): Map[K, Array[T]]  按条件分组，条件由 f 匹配，返回值是Map类型，每个key对应一个序列。（条件最多23个）
    val aGroupBy = Array(1, 2, 3, 4)
    val bGroupBy = aGroupBy.groupBy(f = x => x match {
      case x if (x < 3) => "small"
      case _ => "big"
    })
    val stringToInts: Map[String, Array[Int]] = aGroupBy.groupBy(x => x match {
      case x if (x < 3) => "small" //小于3的 对应key 为small
      case _ => "big"
    })
    stringToInts.keySet.foreach(println(_))
    stringToInts.get("small").foreach(println(_)) // 1 2
    //def grouped(size: Int): collection.Iterator[Array[T]] 按指定数量分组，每组有 size 数量个元素，返回一个集合
    //可能有不满足size数量的情况
    val aGrouped = Array(1, 2, 3, 4, 5,12)
    val bGrouped = aGrouped.grouped(2).toList
    bGrouped.foreach((x) => println("第" + (bGrouped.indexOf(x) + 1) + "组:" + x.mkString(",")))
    /* 第1组:1
     第2组:2
     第3组:3
     第4组:4
     第5组:5
 */
    //def hasDefiniteSize: Boolean  检测序列是否存在有限的长度 对应Stream这样的流数据，返回false
    //def head: T  返回头部元素
    val aHead = Array(10, 2, 3,4,5)
    println(aHead.head) //Int = 10
    //def headOption: Option[T]  这个方法得看Option对象的含义
    val aHeadOption = Array(1, 2, 3,4,5)
    println(aHeadOption.headOption)   //Some(1)
    val aHeadOption1:Array[Int] = Array()
    println(aHeadOption1.headOption)   //None
    //indexOf(elem: T) indexOf(elem: T)
    //indexOf(elem: T, from: Int)
    //def indexOfSlice[B >: A](that: GenSeq[B]): Int  检测当前序列中是否包含另一个序列（that），并返回第一个匹配出现的元素的索引,找不到返回-1
    val aIndexOfSlice = Array(1, 3, 2, 3, 4)
    val bIndexOfSlice = Array(2,3)
    println(aIndexOfSlice.indexOfSlice(bIndexOfSlice))  // return 2
    //def indexWhere(p: (T) ⇒ Boolean): Int  返回当前序列中第一个满足 p 条件的元素的索引
    //def indices: collection.immutable.Range  返回当前序列索引集合（对Map无效）
    //def init: Array[T]  返回当前序列中不包含最后一个元素的序列
    val aInit = Array(10, 2, 3, 40, 5)
    val bInit: Array[Int] = aInit.init
    println(bInit.mkString(","))    // 10, 2, 3, 40
    //def inits: collection.Iterator[Array[T]]  ==>List(1,2,3).inits = Iterator(List(1,2,3), List(1,2), List(1), Nil)
    //def intersect(that: collection.Seq[T]): Array[T]  取两个集合的交集
    val aIntersect = Array(1, 2, 3, 4, 5)
    val bIntersect = Array(3, 4, 6)
    val cIntersect = aIntersect.intersect(bIntersect)
    println(cIntersect.mkString(","))
    //；def isEmpty: Boolean  判断当前序列是否为空
    //def isTraversableAgain: Boolean  判断序列是否可以反复遍历(迭代器不能反复遍历，即判断是否是迭代器)
    //def iterator: collection.Iterator[T]  说白了就是返回迭代器
    val aIterator = Array(1, 2, 3, 4, 5)
    val bIterator: Iterator[Int] = aIterator.iterator
    //此时就可以通过迭代器访问 b
    bIterator.foreach(println(_))
    //def last: T 数组中最后一个元素
    //def lastIndexOf(elem: T): Int  取得序列中最后一个等于 elem 的元素的位置，索引值
    //lastIndexOfSlice
    //def lastIndexWhere(p: (T) ⇒ Boolean): Int
    //def lastOption: Option[T] 最后一个
    //def length: Int
    val aLength = Array(1, 2, 3, 4, 5)
    println(aLength.length)   // return  5
    val testLength: Array[Int] = new Array[Int](10);
    println(testLength.length)  //数组长度  10
    println(testLength.size)   //数组中元素个数 10  size 和length是等价的
    //def lengthCompare(len: Int): Int  比较序列的长度和参数 len，根据二者的关系返回不同的值，比较规则是 lenght-len
    //def map[B](f: (A) ⇒ B): Array[B]  对序列中的元素进行 f 操作
    //def max: A 最大值
    //def maxBy[B](f: (A) ⇒ B): A  返回第一个符合条件的元素
    //def min: A 返回数组中的最小元素
    //def minBy[B](f: (A) ⇒ B): A 返回序列中第一个不符合条件的元素
    //def mkString: String 将所有元素组合成一个字符串
    //mkString(sep: String) 将所有元素组合成一个字符串，以 sep 作为元素间的分隔符
    //def mkString(start: String, sep: String, end: String): String  将所有元素组合成一个字符串，以 start 开头，以 sep 作为元素间的分隔符，以 end 结尾
    //def nonEmpty: Boolean 判断序列不是空
    //def padTo(len: Int, elem: A): Array[A] 如果当前序列长度小于 len，那么新产生的序列长度是 len，多出的几个位值填充 elem，如果当前序列大于等于 len ，则返回当前序列
    val aPadTo = Array(1, 2, 3, 4, 5)
    val bPadTo = aPadTo.padTo(2,9)    //需要一个长度为 7  的新序列，空出的填充 9
    println(bPadTo.mkString(","))    // return  1,2,3,4,5,9,9
    //def par: ParArray[T] 将集合转换为并行集合；返回一个并行实现，产生的并行序列，不能被修改。 转成不同的数组
    val aPar = Array(1, 2, 3, 4, 5)
    val bPar: ParArray[Int] = a.par
    // 结果：b: scala.collection.parallel.mutable.ParArray[Int] = ParArray(1, 2, 3, 4, 5)
    //  "ParArray" size = 5
    //def partition(p: (T) ⇒ Boolean): (Array[T], Array[T])
    //按条件将序列拆分成两个新的序列，满足条件的放到第一个序列中，其余的放到第二个序列，下面以序列元素是否是 2 的倍数来拆分
    val aPartition = Array(1, 2, 3, 4, 5)
    val bPartition:(Array[Int],Array[Int]) = aPartition.partition( {x:Int => x % 2 == 0})  //满足条件放1 不满足条件放2
    println(bPartition._1.mkString(","))     // return  2,4
    println(bPartition._2.mkString(","))     // return  1,3,5
    //def patch(from: Int, that: GenSeq[A], replaced: Int): Array[A] 给定一个序列 替换另一个序列的一部分
    val aPatch = Array(1, 2, 3, 4, 5)
    val bPatch = Array(3, 4, 6)
    val cPatch = aPatch.patch(1,bPatch,2)
    println(cPatch.mkString(","))    // return 1,3,4,6,4,5
    /**从 a 的索引1的第二个元素开始，取两个元素，即 2和3 ，这两个元素被替换为 b的内容*/
    //def permutations: collection.Iterator[Array[T]]
    //排列组合，他与combinations不同的是，组合中的内容可以相同，但是顺序不能相同，combinations不允许包含的内容相同，即使顺序不一样
    //def prefixLength(p: (T) ⇒ Boolean): Int  //给定一个条件 p，截止到第一个不满足条件的元素，返回一个前置数列的长度，这个数列中的元素都满足 p
    //def product: A 返回所有元素乘积的值(只能是数值型)
    //def reduce[A1 >: A](op: (A1, A1) ⇒ A1): A1   对序列中的每个元素进行二元运算(一次取2个值)，不需要初始值 同 fold，不需要初始值
    //def repr: Array[A1]  //将序列对象转化为供解释器读取的形式
    //def reverse: Array[T]  反转序列
    //def reverseIterator: collection.Iterator[T]  反向生成迭代
    //def reverseMap[B](f: (A) ⇒ B): Array[B]   同 map 方向相反
    //def sameElements(that: GenIterable[A]): Boolean  判断两个序列是否顺序和对应位置上的元素都一样
    val aSameElements = Array(1,2,3,4,5)
    val bSameElements = Array(1,2,3,4)
    println(aSameElements.sameElements(bSameElements))  // false
    //def scan[B >: A, That](z: B)(op: (B, B) ⇒ B)(implicit cbf: CanBuildFrom[Array[T], B, That]): That
    //用法同 fold，scan会把每一步的计算结果放到一个新的集合中返回，而 fold 返回的是单一的值
    val aScan = Array(1,2,3,4,5)
    val bScan = aScan.scan(5)(_+_)
    println(bScan.mkString(","))    // 5,6,8,11,15,20
    //def segmentLength(p: (T) ⇒ Boolean, from: Int): Int  //从序列的索引 from 处开始向后查找，所有满足 p 的连续元素的长度
    val aSegmentLength = Array(1,2,3,1,1,1,1,1,4,1,5)
    val bSegmentLength = aSegmentLength.segmentLength( {x:Int => x < 3},3)        // 5
    val bSegmentLength1 = aSegmentLength.segmentLength( {x:Int => x < 3},4)        // 4
    //def seq: collection.mutable.IndexedSeq[T] 产生一个引用当前序列的 sequential 视图 就是返回一个IndexedSeq
    val eSeq = Array(1,3,2)
    val seq: mutable.IndexedSeq[Int] = eSeq.seq;
    //def size: Int 等价于 length
    //def slice(from: Int, until: Int): Array[T]  取出当前序列中，from 到 until 之间的片段(左包右不包)
    //sliding(size: Int): collection.Iterator[Array[T]]
    //从第一个元素开始，每个元素和它后面的 size - 1 个元素组成一个数组，最终组成一个新的集合返回，当剩余元素不够 size 数，则停止
    //def sortBy[B](f: (T) ⇒ B)(implicit ord: math.Ordering[B]): Array[T] 按照指定的规则进行排序
    val aSortBy = Array(3,2,1,4,5)
    val bSortBy = aSortBy.sortBy( {x:Int => x})
    println(bSortBy.mkString(","))    // 1,2,3,4,5
    // 倒序
    val bSortBy1 = aSortBy.sortBy( {x:Int => -x})
    println(bSortBy1.mkString(","))    // 5,4,3,2,1
    //def sortWith(lt: (T, T) ⇒ Boolean): Array[T]  自定义排序方法 lt
    val aSortWith = Array(3,2,1,4,5)
    val bSortWith = aSortWith.sortWith(_.compareTo(_) > 0)  // 倒序
    println(bSortWith.mkString(","))    // 5,4,3,2,1
    val bSortWith1 = aSortWith.sortWith(_.compareTo(_) < 0)  // 正序
    println(bSortWith1.mkString(","))    // 1,2,3,4,5

    val ff = Array(("张三",50),("李四",70),("王不二",88))
    val fd = ff.sortBy(x => x._2)
    // fd : Array[(String, Int)] = Array((张三,50), (李四,70), (王不二,88))
    //def sorted[B >: A](implicit ord: math.Ordering[B]): Array[T]  使用默认的排序规则对序列排序（升序）
    //def span(p: (T) ⇒ Boolean): (Array[T], Array[T])
    //分割序列为两个集合，从第一个元素开始，直到找到第一个不满足条件的元素止，之前的元素放到第一个集合，其它的放到第二个集合
    //def splitAt(n: Int): (Array[T], Array[T])  从指定位置开始，把序列拆分成两个集合
    //def startsWith[B](that: GenSeq[B], offset: Int): Boolean
    //从指定偏移处，是否以某个序列开始
    //def stringPrefix: String 返回 toString 结果的前缀
    //def subSequence(start: Int, end: Int): CharSequence 返回 start 和 end 间的字符序列(数组类型必须是Array[Char])(左包右不包)
    //def sum: A 序列求和，元素需为Numeric[T]类型
    //def tail: Array[T]  返回除了当前序列第一个元素的其它元素组成的序列
    //def tails: Array[T]
    //对集合中的元素进行 tail 操作，该操作的返回值中， 第一个值是当前序列的副本，包含当前序列所有的元素，最后一个值是空的，对头尾之间的值进行tail操作，上一步的结果作为下一步的操作对象
    //def take(n: Int): Array[T]
    //返回当前序列中前 n 个元素组成的序列
    //def toArray: Array[A]
    //def toBuffer[A1 >: A]: Buffer[A1]
    //def toIndexedSeq: collection.immutable.IndexedSeq[T]
    //def toIterable: collection.Iterable[T]
    //def toIterator: collection.Iterator[T]  同 iterator 方法
    //def toList: List[T]  同 List 类型
    //def toMap[T, U]: Map[T, U]
    //同 Map 类型，需要被转化序列中包含的元素时 Tuple2 类型数据
    //val chars = Array(("a","b"),("c","d"),("e","f"))
   /* val chars = Array(("a","b"),("c","d"),("e","f"))
    val b = chars.toMap
    println(b)      //Map(a -> b, c -> d, e -> f)

    val a = Array(1,3,4,5,2,5)
    val b = a.map((_,1))
    val c = b.toMap*/
    //def toSeq: collection.Seq[T]  同 Seq 类型
    //def toSet[B >: A]: Set[B] def toSet[B >: A]: Set[B]
    //def toStream: collection.immutable.Stream[T] 同 Stream 类型(流)
    //def toVector: Vector[T]  同 Vector 类型
    //def toTraversable: Traversable[T]
    //def transform(f: T => T): scala.collection.mutable.WrappedArray[T]  提供一个lambda表达式，对序列中所有元素进行替换操作
    //def transpose[U](implicit asArray: (T) ⇒ Array[U]): Array[Array[U]]  矩阵转换，二维数组行列转换(转置)
   /* val chars = Array(Array("a","b"),Array("c","d"),Array("e","f"))
    val b = chars.transpose
    println(b.mkString(","))

    val k = Array(Array(1,3,2),Array(5,8,2),Array(7,9,8),Array(2,7,5))
    val j = k.transpose
    // j: Array[Array[Int]] = Array(Array(1, 5, 7, 2), Array(3, 8, 9, 7), Array(2, 2, 8, 5))*/
    //def union(that: collection.Seq[T]): Array[T]
    //联合两个序列，同操作符 ++(不去重)
    //def unzip[T1, T2](implicit asPair: (T) ⇒ (T1, T2), ct1: ClassTag[T1], ct2: ClassTag[T2]): (Array[T1], Array[T2])
    //将含有两个元素的数组，第一个元素取出组成一个序列，第二个元素组成一个序列
    //def unzip3 将含有三个元素的三个数组，第一个元素取出组成一个序列，第二个元素组成一个序列，第三个元素组成一个序列
    //def update(i: Int, x: T): Unit 将序列中 i 索引处的元素更新为 x
    //def view(from: Int, until: Int): IndexedSeqView[T, Array[T]]
    //返回 from 到 until 间的序列，不包括 until 处的元素
    //def withFilter(p: (T) ⇒ Boolean): FilterMonadic[T, Array[T]]
    //根据条件 p 过滤元素(返回特殊类型FilterMonadic[T, Array[T]])
    //def zip[B](that: GenIterable[B]): Array[(A, B)]
    //将两个序列对应位置上的元素组成一个pair序列
    /*val a = Array(1,2,3,4,5)
    val b = Array(5,4,3,2,1)
    val c = a.zip(b)
    println(c.mkString(","))        //(1,5),(2,4),(3,3),(4,2),(5,1)

    val a = Array(1,2,3,4,5)
    val b = Array(5,4,3,2)
    val c = a.zip(b)
    println(c.mkString(","))        //(1,5),(2,4),(3,3),(4,2)*/
    //def zipAll[B](that: collection.Iterable[B], thisElem: A, thatElem: B): Array[(A, B)]
    //同 zip ，但是允许两个序列长度不一样，不足的自动填充，如果当前序列端，空出的填充为 thisElem，如果 that 短，填充为 thatElem
    //def zipWithIndex: Array[(A, Int)]
    //序列中的每个元素和它的索引组成一个序列






















    println()
  }
}
